#include "openmove_Prefix.h"
#include "SceneBase.h"
#include "OgreEngine.h"
#include "ExampleFrameListener.h"
#include "SkeletalAnimationFrameListener.h"
#include "OgreExternalTextureSourceManager.h"
#include "OgreExternalTextureSource.h"
#include "osc/UdpSocket.h"
#include "NetBase.h"
#include "NetServer.h"
#include <CEGUI/elements/CEGUISlider.h>
#include <CEGUI/elements/CEGUIStaticText.h>
#include <CEGUI/elements/CEGUIScrollbar.h>
#include <CEGUI/elements/CEGUIComboBox.h>
#include "LightEditor.h"
#include "NetBase.h"
#include "NetClient.h"

XERCES_CPP_NAMESPACE_USE

#define SELF_TEST_MODE 0
#define NB_FRAME_BEFORE_READY 60

LightEditor* CSceneBase::m_LightEditorSheet = NULL;

#define DEFAULT_CAMERA_NAME "SimpleCamera"
#define DEFAULT_CLIENT_CAMERA_NAME "ClientSimpleCamera"
#define DEFAULT_CAMERA_NEARCLIP 1.0f
#define DEFAULT_CAMERA_FARCLIP 50000.0f
#define DEFAULT_ENTITY_SHOWBBOX false

static Real timeFromPacket = 0.0f;



CSceneBase :: CSceneBase(COgreEngine &Creator, const String & Name, const int pos) : 
m_pCurrentCamera(NULL),
m_OgreEngine(Creator),
m_pSceneNode(NULL),
m_SceneName(Name),
m_ShowEntitiesBBox(DEFAULT_ENTITY_SHOWBBOX),
m_pCameraFrameListener(NULL),
m_pCameraBone(NULL),
m_NetTimer(0),
m_pCameraMoveEntity(NULL),
m_CameraRot(0),
m_ScenePos(pos),
m_NextEventId(0),
m_CurrentItemSelection(0),
m_LastSelectionTime(0),
m_CurrentObject(NULL),
m_sliding(false),
m_transitionOut(1.0f, 0.0f, 0.0f, false, 5.0f, GpuProgramParametersSharedPtr(NULL), false, false),
m_transitionIn(1.0f, 0.0f, 0.0f, false, 5.0f, GpuProgramParametersSharedPtr(NULL), false, false),
m_Timer(m_NetConfig),
m_interactionTime(0.0f)
{
}

CSceneBase :: ~CSceneBase(void)
{
	delete m_pCameraFrameListener;
}

void CSceneBase :: Create(XERCES_CPP_NAMESPACE::DOMElement const * scene, ENetConfig const &netConfig)
{
	assert(0 == XMLString::compareString(L"scene", scene->getNodeName()));

	bool camDirFound = false;

	TCreatorEntities entities;
	TCreatorNodes nodes;
	TCreatorLights lights;

	for (DOMNode * child = scene->getFirstChild(); NULL != child; child = child->getNextSibling())
	{
		if (0 == XMLString::compareString(L"entities", child->getNodeName()))
		{
			for (DOMNode * entity = child->getFirstChild(); NULL != entity; entity = entity->getNextSibling())
			{
				if (0 == XMLString::compareString(L"entity", entity->getNodeName()))
				{
					DOMElement *element = static_cast<DOMElement *>(entity);
					char const *name = XMLString::transcode(element->getAttribute(L"name"));
					char const *mesh = XMLString::transcode(element->getAttribute(L"mesh"));
					bool castShadow = StringConverter::parseBool(XMLString::transcode(element->getAttribute(L"castShadow")));
					entities.push_back(SEntity(name, mesh, castShadow));
				} else
				if (0 == XMLString::compareString(L"for_entity", entity->getNodeName()))
				{
					DOMElement *element = static_cast<DOMElement *>(entity);
					char const *name = XMLString::transcode(element->getAttribute(L"name"));
					char const *mesh = XMLString::transcode(element->getAttribute(L"mesh"));
					bool castShadow = StringConverter::parseBool(XMLString::transcode(element->getAttribute(L"castShadow")));
					int iteration = StringConverter::parseInt(XMLString::transcode(element->getAttribute(L"iteration")));
					
					for (int i = 1; i < iteration; ++i)
					{
						entities.push_back(SEntity(name + StringConverter::toString(i), mesh + StringConverter::toString(i) + ".mesh", castShadow));
					}
				}
			}
		}
		if (0 == XMLString::compareString(L"nodes", child->getNodeName()))
		{
			for (DOMNode * node = child->getFirstChild(); NULL != node; node = node->getNextSibling())
			{
				if (0 == XMLString::compareString(L"node", node->getNodeName()))
				{
					DOMElement *element = static_cast<DOMElement *>(node);
					char const *name = XMLString::transcode(element->getAttribute(L"name"));
					char const *entity = XMLString::transcode(element->getAttribute(L"entity"));
					Vector3 position = StringConverter::parseVector3(XMLString::transcode(element->getAttribute(L"position")));
					Quaternion rotation = StringConverter::parseQuaternion(XMLString::transcode(element->getAttribute(L"rotation")));
					nodes.push_back(SNode(name, entity, position, rotation));
				} else
				if (0 == XMLString::compareString(L"for_node", node->getNodeName()))
				{
					DOMElement *element = static_cast<DOMElement *>(node);
					char const *name = XMLString::transcode(element->getAttribute(L"name"));
					char const *entity = XMLString::transcode(element->getAttribute(L"entity"));
					Vector3 position = StringConverter::parseVector3(XMLString::transcode(element->getAttribute(L"position")));
					Quaternion rotation = StringConverter::parseQuaternion(XMLString::transcode(element->getAttribute(L"rotation")));
					int iteration = StringConverter::parseInt(XMLString::transcode(element->getAttribute(L"iteration")));
					for (int i = 1; i < iteration; ++i)
					{
						nodes.push_back(SNode(name + StringConverter::toString(i), entity + StringConverter::toString(i), position, rotation));
					}
				}
			}
		}
		if (0 == XMLString::compareString(L"lights", child->getNodeName()))
		{
			for (DOMNode * light = child->getFirstChild(); NULL != light; light = light->getNextSibling())
			{
				if (0 == XMLString::compareString(L"light", light->getNodeName()))
				{
					DOMElement *element = static_cast<DOMElement *>(light);
					char const *name = XMLString::transcode(element->getAttribute(L"name"));
					Vector3 position = StringConverter::parseVector3(XMLString::transcode(element->getAttribute(L"position")));
					ColourValue diffuse = StringConverter::parseColourValue(XMLString::transcode(element->getAttribute(L"diffuse")));
					ColourValue specular = StringConverter::parseColourValue(XMLString::transcode(element->getAttribute(L"specular")));
					String const typeStr = XMLString::transcode(element->getAttribute(L"type"));
					Light::LightTypes type = Light::LT_POINT;
					if ("directional" == typeStr)
					{
						type = Light::LT_DIRECTIONAL;
					} else 
					if ("spotlight" == typeStr)
					{
						type = Light::LT_SPOTLIGHT;
					}
					Vector3 direction = StringConverter::parseVector3(XMLString::transcode(element->getAttribute(L"direction")));
					bool castShadow = StringConverter::parseBool(XMLString::transcode(element->getAttribute(L"castShadow")));
					
					DOMNodeList *list = element->getElementsByTagName(L"direction");
					if (NULL != list && 0 < list->getLength())
					{
						DOMElement *dirElement = static_cast<DOMElement *>(list->item(0));
						String const x = XMLString::transcode(dirElement->getAttribute(L"x"));
						String const y = XMLString::transcode(dirElement->getAttribute(L"y"));
						String const z = XMLString::transcode(dirElement->getAttribute(L"z"));
						String const vector = XMLString::transcode(dirElement->getAttribute(L"vector"));
						direction = Quaternion(Degree(StringConverter::parseReal(x)), Vector3::UNIT_X) * 
							Quaternion(Degree(StringConverter::parseReal(y)), Vector3::UNIT_Y) *
							Quaternion(Degree(StringConverter::parseReal(z)), Vector3::UNIT_Z) *
							StringConverter::parseVector3(vector);
					}

					lights.push_back(SLight(name, position, diffuse, specular, type, direction, castShadow));
				}
			}
		}
		if (0 == XMLString::compareString(L"cam_direction", child->getNodeName()))
		{
			DOMElement *dirElement = static_cast<DOMElement *>(child);
			String const x = XMLString::transcode(dirElement->getAttribute(L"x"));
			String const y = XMLString::transcode(dirElement->getAttribute(L"y"));
			String const z = XMLString::transcode(dirElement->getAttribute(L"z"));
			String const vector = XMLString::transcode(dirElement->getAttribute(L"vector"));
			m_resetParams.m_camOrientation = Quaternion(Degree(StringConverter::parseReal(x)), Vector3::UNIT_X) * 
				Quaternion(Degree(StringConverter::parseReal(y)), Vector3::UNIT_Y) *
				Quaternion(Degree(StringConverter::parseReal(z)), Vector3::UNIT_Z);
			m_resetParams.m_camDirection = m_resetParams.m_camOrientation * -Vector3::UNIT_Z;
			camDirFound = true;
		}
		if (0 == XMLString::compareString(L"transitionOut", child->getNodeName()))
		{
			DOMElement *transElement = static_cast<DOMElement *>(child);
			setTransitionFromXml(m_transitionOut, transElement);
		}
		if (0 == XMLString::compareString(L"transitionIn", child->getNodeName()))
		{
			DOMElement *transElement = static_cast<DOMElement *>(child);
			setTransitionFromXml(m_transitionIn, transElement);
		}
	}
	m_resetParams.m_camPosition = StringConverter::parseVector3(XMLString::transcode(scene->getAttribute(L"camPosition")));
	if (!camDirFound)
	{
		m_resetParams.m_camDirection = StringConverter::parseVector3(XMLString::transcode(scene->getAttribute(L"camDirection")));
		Vector3 z(-Vector3::UNIT_Z);
		m_resetParams.m_camOrientation = z.getRotationTo(m_resetParams.m_camDirection);
	}
	m_resetParams.m_bgColor = StringConverter::parseColourValue(XMLString::transcode(scene->getAttribute(L"bgColor")));
	m_resetParams.m_skyboxName = XMLString::transcode(scene->getAttribute(L"skyboxName"));
	m_resetParams.m_shadowTexSize = StringConverter::parseInt(XMLString::transcode(scene->getAttribute(L"shadowTexSize")));
	m_resetParams.m_shadowFarDist = StringConverter::parseReal(XMLString::transcode(scene->getAttribute(L"shadowFarDist")));
	m_resetParams.m_shadowColor = StringConverter::parseColourValue(XMLString::transcode(scene->getAttribute(L"shadowColor")));
	m_resetParams.m_aspectRatio = StringConverter::parseReal(XMLString::transcode(scene->getAttribute(L"aspectRatio")));
	m_resetParams.m_duration = StringConverter::parseReal(XMLString::transcode(scene->getAttribute(L"duration")));
	m_resetParams.m_realDuration = m_resetParams.m_duration;

	m_ShowEntitiesBBox = StringConverter::parseBool(XMLString::transcode(scene->getAttribute(L"showBoundingBox")));
	m_resetParams.m_camSideAngle = Degree(StringConverter::parseReal(XMLString::transcode(scene->getAttribute(L"camSideAngle"))));
	m_resetParams.m_FOVy = Degree(StringConverter::parseReal(XMLString::transcode(scene->getAttribute(L"angleOfView"))) / 1.33f);

	Create(entities, nodes, lights, netConfig);
	m_pSceneNode->setVisible(false);
}

void CSceneBase :: setTransitionFromXml(STransition &transition, DOMElement const *transElement)
{
	String const black = XMLString::transcode(transElement->getAttribute(L"black"));
	String const deform = XMLString::transcode(transElement->getAttribute(L"deform"));
	String const add = XMLString::transcode(transElement->getAttribute(L"add"));
	String const deform_anim = XMLString::transcode(transElement->getAttribute(L"deform_anim"));
	String const duration = XMLString::transcode(transElement->getAttribute(L"duration"));
	String const isBW = XMLString::transcode(transElement->getAttribute(L"bw"));

	transition.m_black = StringConverter::parseReal(black);
	transition.m_deform = StringConverter::parseReal(deform);
	transition.m_add = StringConverter::parseReal(add);
	transition.m_duration = StringConverter::parseReal(duration);
	transition.m_deformAnim = StringConverter::parseBool(deform_anim);
	transition.m_isBW = StringConverter::parseBool(isBW);
}

void CSceneBase :: Create(TCreatorEntities const &CreatorEntities, TCreatorNodes const &CreatorNodes, TCreatorLights const &CreatorLights, ENetConfig IsClient, Vector3 &CameraStartPos)
{
	m_pCurrentCamera = m_OgreEngine.m_pCurrentSceneManager->createCamera(m_SceneName + "_" DEFAULT_CAMERA_NAME);
	m_pCurrentCamera->setNearClipDistance(DEFAULT_CAMERA_NEARCLIP);
	m_pCurrentCamera->setFarClipDistance(DEFAULT_CAMERA_FARCLIP);
	m_pCurrentCamera->setPosition(CameraStartPos);

	m_NetConfig = IsClient;
	if (IsClient == e_NCClientR || IsClient == e_NCClientL)
	{
		Camera *pTmpCamera = m_OgreEngine.m_pCurrentSceneManager->createCamera(m_SceneName + "_" DEFAULT_CLIENT_CAMERA_NAME);
		m_pCameraFrameListener = new ExampleFrameListener(m_OgreEngine.m_pCurrentRenderWindow, pTmpCamera, this);
	}
	else
	{
		m_pCameraFrameListener = new ExampleFrameListener(m_OgreEngine.m_pCurrentRenderWindow, m_pCurrentCamera, this);
	}

	m_Timer.m_netConfig = IsClient;

	//m_OgreEngine.m_Root.addFrameListener(m_pCameraFrameListener);

	m_FrameListeners.push_back(m_pCameraFrameListener);
	m_FrameListeners.push_back(this);

	m_pSceneNode = m_OgreEngine.m_pCurrentSceneManager->createSceneNode(m_SceneName);
	m_OgreEngine.m_pCurrentSceneManager->getRootSceneNode()->addChild(m_pSceneNode);
	m_pSceneNode->setVisible(false);

	m_OgreEngine.m_pCurrentSceneManager->setSkyBox(false, "");

	AddLights(CreatorLights);

	AddGeometries(CreatorEntities, CreatorNodes);

	m_Timer.reset();
	m_NetTimer = 0;

	m_pCameraFrameListener->setMoveCamera(false);
	m_KeyListeners.push_back(this);

	m_OgreEngine.addScene(this);

	for (size_t i = 0; i < e_NbCamera; ++i)
	{
		m_pCameraFrutsumNode[i] = m_OgreEngine.m_pCurrentSceneManager->getRootSceneNode()->createChildSceneNode();
		m_pCameraFrutsum[i] = m_OgreEngine.m_pCurrentSceneManager->createCamera(m_SceneName + "_" DEFAULT_CLIENT_CAMERA_NAME + StringConverter::toString(i));
		m_pCameraFrutsumNode[i]->attachObject(m_pCameraFrutsum[i]);
		m_pCameraFrutsum[i]->setVisible(false);
		m_pCameraFrutsumNode[i]->setVisible(false);
	}

	setupSheet();
	setupEventHandlers();
}

void CSceneBase :: Reset(void)
{
	m_Timer.reset();
	m_NetTimer = 0;
	StopAnimations();
	StartAnimations();
	CSyncManager::getSingleton().m_Timer.reset();

	srand(0);

	m_isSceneReady = false;
	nbFrameElapsed = 0;
	m_interactionTime = 0;
}

void CSceneBase :: Attach(void)
{
	htMutexLock(&CSyncManager::getSingleton().m_updateMutex);
	memset(m_animPacket, 0, MAX_ANIM * sizeof(Real));
	htMutexUnlock(&CSyncManager::getSingleton().m_updateMutex);

	m_canSetScene = true;
	LogManager::getSingleton().logMessage("Attach");
	//m_OgreEngine.m_pCurrentSceneManager->getRootSceneNode()->addChild(m_pSceneNode);
	m_OgreEngine.m_pCurrentSceneManager->setAmbientLight(m_AmbientColour);

	unsigned short nbLightCastingShadows = 0;
	for (TSceneLights::iterator It = m_SceneLights.begin(); It != m_SceneLights.end(); ++It)
	{
		Light * pLight = m_OgreEngine.m_pCurrentSceneManager->createLight(It->m_Name);
		pLight->setType(It->getType());
		pLight->setPosition(It->getPosition());
		pLight->setDiffuseColour(It->getDiffuseColour());
		pLight->setSpecularColour(It->getSpecularColour());
		pLight->setCastShadows(It->getCastShadows());
		pLight->setAttenuation(8000, 1, 0.0005, 0);
		pLight->setDirection(It->getDirection());
		pLight->setSpotlightInnerAngle(It->getSpotlightInnerAngle());
		pLight->setSpotlightOuterAngle(It->getSpotlightOuterAngle());

		if (pLight->getCastShadows())
			++nbLightCastingShadows;

		m_Lights.push_back(pLight);
	}

	unsigned short nbShadowTex = std::min((unsigned short)std::max(nbLightCastingShadows, (unsigned short)1), (unsigned short)8);
	m_OgreEngine.m_pCurrentSceneManager->setShadowTextureCount(nbShadowTex);
	m_OgreEngine.m_pViewPort->setCamera(m_pCurrentCamera);

	if (m_NetConfig == e_NCNone)
	{
		StartAnimations();
	}

	for (TCompositors::iterator It = m_Compositors.begin(); It != m_Compositors.end(); ++It)
	{
		CompositorInstance *pCompositor = CompositorManager::getSingleton().addCompositor(m_OgreEngine.m_pViewPort, (*It).m_name);
		if (NULL != pCompositor)
		{
			(*It).m_compositor = pCompositor;
			pCompositor->setEnabled(true);
		}
	}
	m_transitionCompositor[0] = NULL;
	m_transitionCompositor[1] = NULL;
	{
		CompositorInstance *pCompositor = CompositorManager::getSingleton().addCompositor(m_OgreEngine.m_pViewPort, "TransitionIn");
		if (NULL != pCompositor)
		{
			m_transitionCompositor[0] = pCompositor;
			pCompositor->setEnabled(true);
		}
		pCompositor = CompositorManager::getSingleton().addCompositor(m_OgreEngine.m_pViewPort, "TransitionOut");
		if (NULL != pCompositor)
		{
			m_transitionCompositor[1] = pCompositor;
			pCompositor->setEnabled(false);
		}
		m_transitionIn.m_fpParams.setNull();
		m_transitionOut.m_fpParams.setNull();
		m_transitionIn.m_isActive = true;
		m_transitionOut.m_isActive = false;
	}


	Reset();

	//AddListeners();
	m_pSceneNode->setVisible(true);
	//m_pWebcamPlugin->disableAll();	

	m_OgreEngine.m_pCurrentSceneManager->setFog(FOG_NONE, ColourValue::White, 0.001f, 0.0f, 1.0f);

	//m_pCurrentCamera->setDirection(m_resetParams.m_camDirection);
	//m_pCurrentCamera->setPosition(m_resetParams.m_camPosition);
	SetCamera(m_resetParams.m_camPosition, m_resetParams.m_camOrientation);
	m_pCurrentCamera->setFOVy(m_resetParams.m_FOVy);
	m_pCurrentCamera->setAspectRatio(m_resetParams.m_aspectRatio);
	
	if (nbLightCastingShadows > 0)
	{
		m_OgreEngine.m_pCurrentSceneManager->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE);
		m_OgreEngine.m_pCurrentSceneManager->setShadowTextureSize(m_resetParams.m_shadowTexSize);
		m_OgreEngine.m_pViewPort->setShadowsEnabled(true);
	}
	else
	{
		m_OgreEngine.m_pCurrentSceneManager->setShadowTechnique(SHADOWTYPE_NONE);
		m_OgreEngine.m_pCurrentSceneManager->setShadowTextureSize(16);
		m_OgreEngine.m_pViewPort->setShadowsEnabled(false);
	}

	m_OgreEngine.m_pCurrentSceneManager->setShadowFarDistance(m_resetParams.m_shadowFarDist);
	m_OgreEngine.m_pCurrentSceneManager->setShadowColour(m_resetParams.m_shadowColor);
	m_OgreEngine.m_pCurrentSceneManager->setShadowTextureSelfShadow(false);
	
	m_OgreEngine.m_pViewPort->setBackgroundColour(m_resetParams.m_bgColor);
	m_OgreEngine.m_pCurrentSceneManager->setSkyBox("" != m_resetParams.m_skyboxName, m_resetParams.m_skyboxName);

	if (NULL != m_OgreEngine.m_GUISystem && NULL != m_GuiSheet && NULL != m_OgreEngine.m_pEventProcessor)
	{
		m_OgreEngine.m_GUISystem->setGUISheet(m_GuiSheet);
		m_LightEditorSheet->attach(m_GuiSheet);
	}

	CSyncManager::getSingleton().m_currentCamera = m_pCurrentCamera;

	for (TCompositors::iterator It = m_Compositors.begin(); It != m_Compositors.end(); ++It)
	{
		CompositorInstance *pCompositor = (*It).m_compositor;
		if (NULL != pCompositor)
		{
			pCompositor->addListener(this);
		}
	}
	m_transitionCompositor[0]->addListener(this);
	m_transitionCompositor[1]->addListener(this);

	CompositorManager::getSingleton().setCompositorEnabled(m_OgreEngine.m_pViewPort, "TransitionIn", true);
	CompositorManager::getSingleton().setCompositorEnabled(m_OgreEngine.m_pViewPort, "TransitionOut", false);
	m_transitionIn.m_isActive = true;
	m_transitionOut.m_isActive = false;

	m_transitionInIsPassed = false;

	SetCamera(m_resetParams.m_camPosition, m_resetParams.m_camOrientation);
}

void CSceneBase :: Detach(void)
{
	m_pSceneNode->setVisible(false);

	StopAnimations();

	m_OgreEngine.m_pCurrentSceneManager->destroyAllLights();
	m_Lights.clear();

	for (TCompositors::iterator It = m_Compositors.begin(); It != m_Compositors.end(); ++It)
	{
		CompositorInstance *pCompositor = (*It).m_compositor;
		if (NULL != pCompositor)
		{
			pCompositor->removeListener(this);
		}
	}

	for (TCompositors::iterator It = m_Compositors.begin(); It != m_Compositors.end(); ++It)
	{
		CompositorManager::getSingleton().removeCompositor(m_OgreEngine.m_pViewPort, (*It).m_name);
	}

	m_transitionCompositor[0]->removeListener(this);
	m_transitionCompositor[1]->removeListener(this);

	CompositorManager::getSingleton().removeCompositor(m_OgreEngine.m_pViewPort, "TransitionIn");
	CompositorManager::getSingleton().removeCompositor(m_OgreEngine.m_pViewPort, "TransitionOut");

	m_OgreEngine.m_GUISystem->setGUISheet(NULL);
	m_OgreEngine.m_pCurrentSceneManager->setSkyBox(false, "");

	m_transitionIn.m_fpParams.setNull();
	m_transitionOut.m_fpParams.setNull();

	CSyncManager::getSingleton().m_currentCamera = NULL;

	m_transitionInIsPassed = false;

	Ogre::LogManager::getSingleton().logMessage("Detach");
}

void CSceneBase :: AddListeners(void)
{
	for (CSceneBase::TFrameListeners::iterator ItFrame = m_FrameListeners.begin(); ItFrame != m_FrameListeners.end(); ++ItFrame)
	{
		m_OgreEngine.m_Root.addFrameListener((*ItFrame));
	}
	for (CSceneBase::TKeyListeners::iterator ItKey = m_KeyListeners.begin(); ItKey != m_KeyListeners.end(); ++ItKey)
	{
		m_OgreEngine.m_pEventProcessor->addKeyListener((*ItKey));
	}	

	m_OgreEngine.m_pEventProcessor->addMouseMotionListener(this);
	m_OgreEngine.m_pEventProcessor->addMouseListener(this);
	m_OgreEngine.m_pEventProcessor->addKeyListener(this);
}

void CSceneBase :: RemoveListeners(void)
{
	for (TFrameListeners::iterator It = m_FrameListeners.begin(); It != m_FrameListeners.end(); ++It)
	{
		m_OgreEngine.m_Root.removeFrameListener(*It);
	}

	for (TKeyListeners::iterator It = m_KeyListeners.begin(); It != m_KeyListeners.end(); ++It)
	{
		m_OgreEngine.m_pEventProcessor->removeKeyListener(*It);
	}

	if (NULL != m_OgreEngine.m_GUISystem && NULL != m_GuiSheet && NULL != m_OgreEngine.m_pEventProcessor)
	{
		m_OgreEngine.m_pEventProcessor->removeMouseMotionListener(this);
		m_OgreEngine.m_pEventProcessor->removeMouseListener(this);
		m_OgreEngine.m_pEventProcessor->removeKeyListener(this);
	}
}

void CSceneBase :: Destroy(void)
{
	RemoveListeners();
	m_FrameListeners.clear();
	m_KeyListeners.clear();

	for (TFrustums::iterator It = m_Frustums.begin(); It != m_Frustums.end(); ++It)
	{
		delete (*It);
	}
	m_Frustums.clear();

	m_OgreEngine.m_pCurrentSceneManager->destroyCamera(m_pCurrentCamera);
	m_OgreEngine.m_pCurrentSceneManager->destroySceneNode(m_SceneName);
}

void CSceneBase :: AddNodes(TCreatorNodes const &CreatorNodes)
{
	for (TCreatorNodes::const_iterator It = CreatorNodes.begin(); It != CreatorNodes.end(); ++It)
	{
		SceneNode * pNode = m_pSceneNode->createChildSceneNode(It->m_Name, It->m_Position);
		pNode->attachObject(m_OgreEngine.m_pCurrentSceneManager->getEntity(It->m_EntityName));
		//pNode->showBoundingBox(m_ShowEntitiesBBox);
		pNode->setOrientation(It->m_Rotation);
	}
}

void CSceneBase :: AddEntities(TCreatorEntities const &CreatorEntities)
{
	for (TCreatorEntities::const_iterator It = CreatorEntities.begin(); It != CreatorEntities.end(); ++It)
	{
		Entity *pEntity = m_OgreEngine.m_pCurrentSceneManager->createEntity(It->m_Name, It->m_Filename);
		pEntity->setCastShadows(It->m_CastShadow);
		pEntity->setVisibilityFlags(0x1);
		m_Entities.push_back(pEntity);

		unsigned short src, dest;
        if (!pEntity->getMesh()->suggestTangentVectorBuildParams(src, dest))
		{
            pEntity->getMesh()->buildTangentVectors(src, dest);
		}
	}
}

void CSceneBase :: AddGeometries(TCreatorEntities const &CreatorEntities, TCreatorNodes const &CreatorNodes)
{
	AddEntities(CreatorEntities);
	AddNodes(CreatorNodes);
}

Entity * CSceneBase :: findEntity(String &Name)
{
	for (TEntities::iterator ItEntity = m_Entities.begin(); ItEntity != m_Entities.end(); ++ItEntity)
	{
		if ((*ItEntity)->getName() == Name)
		{
			return (*ItEntity);
		}
	}

	return (NULL);
}

Light * CSceneBase :: findLight(String &Name)
{
	for (TLights::iterator ItLight = m_Lights.begin(); ItLight != m_Lights.end(); ++ItLight)
	{
		if ((*ItLight)->getName() == Name)
		{
			return (*ItLight);
		}
	}

	return (NULL);
}

void CSceneBase :: StartAnimations(void)
{
	for (TEntities::iterator ItEntity = m_Entities.begin(); ItEntity != m_Entities.end(); ++ItEntity)
	{
		AnimationStateSet *pStateSet = (*ItEntity)->getAllAnimationStates();
		if (NULL != pStateSet)
		{
			AnimationStateIterator It = pStateSet->getAnimationStateIterator();
			while(It.hasMoreElements())
			{
				AnimationState * pState = It.getNext();
				pState->setTimePosition(0);
				pState->setEnabled(true);
				pState->setLoop(false);

				if (pState->getAnimationName() == "camera")
				{

					if ((*ItEntity)->getSkeleton()->getNumBones() > 1)
					{
						m_pCameraBone = (*ItEntity)->getSkeleton()->getBone(1);
					}
					else
					{
						m_pCameraBone = (*ItEntity)->getSkeleton()->getBone(0);
					}

					m_pCameraMoveEntity = (*ItEntity);
				}
			}
		}
	}
}

Real CSceneBase :: GetAnimationsFrame(void)
{	
	/*
	if (!m_Timer.m_UseManualTime)
	{
		if ((e_NCServer == m_NetConfig || e_NCNone == m_NetConfig) && m_NetTimer < m_Timer.getMilliseconds())
		//if (1)
		{
			return (m_Timer.getMilliseconds());
		}
		return (m_NetTimer);
	}
	
	return (m_Timer.m_ManualTime);
	*/
	if (e_NCServer == m_NetConfig || e_NCNone == m_NetConfig)
	{
		return (m_Timer.getMilliseconds());
	}

	return (m_Timer.getMilliseconds());
	//return (m_NetTimer);
}

void CSceneBase :: SetAnimationsFrame(Real const &Frame)
{
	m_NetTimer = Frame;
}

void CSceneBase :: StopAnimations(void)
{
	for (TEntities::iterator ItEntity = m_Entities.begin(); ItEntity != m_Entities.end(); ++ItEntity)
	{
		AnimationStateSet *pStateSet = (*ItEntity)->getAllAnimationStates();
		if (NULL != pStateSet)
		{
			AnimationStateIterator It = pStateSet->getAnimationStateIterator();
			while(It.hasMoreElements())
			{
				AnimationState * pState = It.getNext();
				pState->setEnabled(false);
			}
		}
	}

	for (TFrameListeners::iterator It = m_AnimFrameListeners.begin(); It != m_AnimFrameListeners.end(); ++It)
	{
		m_OgreEngine.m_Root.removeFrameListener(*It);
	}

	for (TKeyListeners::iterator It = m_AnimKeyListeners.begin(); It != m_AnimKeyListeners.end(); ++It)
	{
		m_OgreEngine.m_pEventProcessor->removeKeyListener(*It);
	}
}

void CSceneBase :: RemoveGeometries(void)
{
	m_pSceneNode->removeAndDestroyAllChildren();	

	for (TEntities::iterator It = m_Entities.begin(); It != m_Entities.end(); ++It)
	{
		m_OgreEngine.m_pCurrentSceneManager->destroyEntity(*It);
	}
}

void CSceneBase :: AddLights(TCreatorLights const &CreatorLights)
{
	//m_OgreEngine.m_pCurrentSceneManager->setAmbientLight(ColourValue(0.2, 0.2, 0.2));
	//Entity *pLightEntity = m_OgreEngine.m_pCurrentSceneManager->createEntity("directionalLight", "directionalLight.mesh");

	for (TCreatorLights::const_iterator It = CreatorLights.begin(); It != CreatorLights.end(); ++It)
	{
		if (It->m_Name == "Ambient")
		{
			m_AmbientColour = It->m_Diffuse;
		}
		else
		{
			SceneLight light;
			light.m_Name = It->m_Name;
			light.setType(It->m_Type);
			light.setPosition(It->m_Position);
			light.setDiffuseColour(It->m_Diffuse);
			light.setSpecularColour(It->m_Specular);
			light.setCastShadows(It->m_CastShadow);
			light.setAttenuation(8000, 1, 0.0005, 0);
			light.setDirection(It->m_Direction);
			
			m_SceneLights.push_back(light);

			if (m_ShowEntitiesBBox)
			{
				Entity *entity = m_OgreEngine.m_pCurrentSceneManager->createEntity(It->m_Name, "light.mesh");
				SceneNode *node = m_pSceneNode->createChildSceneNode(It->m_Name);
				node->setPosition(light.getPosition());
				node->scale(10, 10, 10);
				node->attachObject(entity);
				node->setDirection(It->m_Direction);

				m_Entities.push_back(entity);
			}
		}
	}
}

SProjectorFrustum CSceneBase :: CreateProjector(String const &ProjectorName, Vector3 const &Position, Vector3 const &Direction)
{
	m_Frustums.push_back(new Frustum);
	Frustum *pDecalFrustum = m_Frustums.back();

	//pDecalFrustum->setNearClipDistance(1.0f);
	//pDecalFrustum->setProjectionType(PT_ORTHOGRAPHIC);
	//pDecalFrustum->setFOVy(Radian(Math::PI/4.0f));
	//pDecalFrustum->setFOVy(m_Focal);
	pDecalFrustum->setVisible(m_ShowEntitiesBBox);

	
	SceneNode * projectorNode;
	if (m_ShowEntitiesBBox)
	{
		projectorNode = m_pSceneNode->createChildSceneNode(ProjectorName);
	}
	else
	{
		projectorNode = m_OgreEngine.m_pCurrentSceneManager->getRootSceneNode()->createChildSceneNode(ProjectorName);
	}
	projectorNode->showBoundingBox(m_ShowEntitiesBBox);
	projectorNode->setVisible(m_ShowEntitiesBBox);
	projectorNode->attachObject(pDecalFrustum);
	projectorNode->setPosition(Position);
	projectorNode->setDirection(Direction);

	//decalFrustum->setProjectionType(PT_ORTHOGRAPHIC);
	//decalFrustum->setNearClipDistance(25);

	m_Frustums.push_back(new Frustum);
	Frustum *pPerpFrustum = m_Frustums.back();

	pPerpFrustum->setProjectionType(PT_ORTHOGRAPHIC); 
	pPerpFrustum->setVisible(m_ShowEntitiesBBox);
	SceneNode *pPerpNode = projectorNode->createChildSceneNode("Filter" + ProjectorName); 
	pPerpNode->showBoundingBox(m_ShowEntitiesBBox);
	pPerpNode->setVisible(m_ShowEntitiesBBox);
	pPerpNode->attachObject(pPerpFrustum); 
	Vector3 up = Vector3::UNIT_Y;
	pPerpNode->rotate(Quaternion(Degree(-90), up)); 

	return (SProjectorFrustum(pDecalFrustum, pPerpFrustum));
}

SProjectorFrustum CSceneBase :: CreateProjector(String const &ProjectorName, Vector3 const &Position, Quaternion const &Orientation)
{
	SProjectorFrustum pDecalFrustum = CreateProjector(ProjectorName, Position, Vector3(1, 0, 0));
	if (m_ShowEntitiesBBox)
	{
		m_pSceneNode->getChild(ProjectorName)->setOrientation(Orientation);
	}
	else
	{
		m_OgreEngine.m_pCurrentSceneManager->getRootSceneNode()->getChild(ProjectorName)->setOrientation(Orientation);
	}

	return (pDecalFrustum);
}

void CSceneBase :: ApplyDecalToMaterial(String const &TextureSourceName, String const &matName, Frustum * pDecalFrustum, TextureUnitState::TextureAddressingMode const &TextureMode)
{
	// get the material
	MaterialPtr mat = (MaterialPtr)MaterialManager::getSingleton().getByName(matName);

	//$ProjectiveDecalApplication.makeMaterialReceiveDecal().createPass
	// create a new pass in the material to render the decal
	
	Pass *pass = mat->getTechnique(0)->getPass(0);//mat->getTechnique(0)->createPass();

	//$ProjectiveDecalApplication.makeMaterialReceiveDecal().decalTexture
	// set up the decal's texture unit

	TextureUnitState *texState = pass->createTextureUnitState(TextureSourceName);
	texState->setProjectiveTexturing(true, pDecalFrustum);
	texState->setTextureAddressingMode(TextureMode);
	texState->setTextureFiltering(FO_NONE, FO_NONE, FO_NONE);
	texState->setColourOperationEx(LBX_BLEND_CURRENT_ALPHA, LBS_TEXTURE, LBS_CURRENT);
	//texState->setColourOperation(LBO_MODULATE);
	texState->setTextureBorderColour(ColourValue(1.0f, 1.0f, 1.0f, 0.0f));

	//TextureUnitState *texState2 = pass->createTextureUnitState(TextureSourceName + "2");
	//texState2->setProjectiveTexturing(true, pDecalFrustum);
	//texState2->setTextureAddressingMode(TextureMode);
	//texState2->setTextureFiltering(FO_NONE, FO_NONE, FO_NONE);
	//texState2->setColourOperationEx(LBX_BLEND_CURRENT_ALPHA, LBS_TEXTURE, LBS_CURRENT, ColourValue::Black, ColourValue::Black);
	//texState2->setTextureBorderColour(ColourValue(1.0f, 1.0f, 1.0f, 0.0f));


	//$ProjectiveDecalApplication.makeMaterialReceiveDecal().passBlend
	// set our pass to blend the decal over the model's regular texture
	//pass->setSceneBlending(SBT_MODULATE);
	//pass->setDepthBias(1);

	//$ProjectiveDecalApplication.makeMaterialReceiveDecal().passLighting
	// set the decal to be self illuminated instead of lit by scene lighting
	pass->setLightingEnabled(false);
}

static Vector3 lastUp = Vector3(0, 1, 0);
static bool displayCameraDetails = false;

bool CSceneBase :: frameStarted(const FrameEvent& evt)
{
	if (0)
	{
		for (int i = 5; i < 15; ++i)
		{
			m_OgreEngine.setDebugText("movie " + StringConverter::toString(i) + 
				": " + StringConverter::toString(CSyncManager::getSingleton().m_moviesFrame[i]));
		}
	}

	m_pSceneNode->_update(true, true);

	updateAnim(evt);

	Vector3 clientPosition = Vector3::ZERO;
	Quaternion clientOrientation = Quaternion::IDENTITY;

	//if (m_NetConfig == e_NCNone || m_NetConfig == e_NCServer)
	if (1)
	{
		if (NULL != m_pCameraBone)
		{
			if (m_pCameraFrameListener->getMoveCamera() == false)
			{
				if (m_NetConfig == e_NCNone || m_NetConfig == e_NCServer)
				{
					SetCamera(m_pCameraBone->getWorldPosition(), m_pCameraBone->getWorldOrientation());
				}
				else
				{
					clientPosition = m_pCameraBone->getWorldPosition();
					clientOrientation = m_pCameraBone->getWorldOrientation();
				}
				m_pCameraMoveEntity->setDisplaySkeleton(false);
				for (size_t i = 0; i < e_NbCamera; ++i)
				{
					if (m_pCameraFrutsumNode[i]->getParentSceneNode() == m_pSceneNode)
					{
						m_OgreEngine.m_pCurrentSceneManager->getRootSceneNode()->addChild(m_pCameraFrutsumNode[i]);
					}
					m_pCameraFrutsum[i]->setVisible(false);
					m_pCameraFrutsumNode[i]->setVisible(false);
				}

				lastUp = m_pCurrentCamera->getUp();
			}
			else
			{
				if (m_NetConfig == e_NCNone || m_NetConfig == e_NCServer)
				{
					SetCamera(m_pCameraBone->getWorldPosition(), m_pCameraBone->getWorldOrientation(), true);
				}
				else
				{
					clientPosition = m_pCameraBone->getWorldPosition();
					clientOrientation = m_pCameraBone->getWorldOrientation();
				}
				m_pCameraMoveEntity->setDisplaySkeleton(true);
				for (size_t i = 0; i < e_NbCamera; ++i)
				{
					m_pCameraFrutsum[i]->setVisible(true);
					m_pCameraFrutsumNode[i]->setVisible(true);
					if (m_pCameraFrutsumNode[i]->getParentSceneNode() != m_pSceneNode)
					{
						m_pSceneNode->addChild(m_pCameraFrutsumNode[i]);
					}
				}
			}
		}
		else
		{
			for (size_t i = 0; i < e_NbCamera; ++i)
			{
				if (m_pCameraFrutsumNode[i]->getParentSceneNode() == m_pSceneNode)
				{
					m_OgreEngine.m_pCurrentSceneManager->getRootSceneNode()->addChild(m_pCameraFrutsumNode[i]);
				}
				m_pCameraFrutsum[i]->setVisible(false);
				m_pCameraFrutsumNode[i]->setVisible(false);
			}

			if (m_pCameraFrameListener->getMoveCamera() == false)
			{
				//SetCamera(m_resetParams.m_camPosition, m_resetParams.m_camOrientation);
				if (m_NetConfig != e_NCNone && m_NetConfig != e_NCServer)
				{
					clientPosition = m_resetParams.m_camPosition;
					clientOrientation = m_resetParams.m_camOrientation;
				}
			}
			else
			{
				if (m_NetConfig == e_NCNone || m_NetConfig == e_NCServer)
				{
					SetCamera(m_resetParams.m_camPosition, m_resetParams.m_camOrientation, true);
				}
				else
				{
					clientPosition = m_resetParams.m_camPosition;
					clientOrientation = m_resetParams.m_camOrientation;
				}
			}
		}
	}
	else
	{
		for (size_t i = 0; i < e_NbCamera; ++i)
		{
			if (m_pCameraFrutsumNode[i]->getParentSceneNode() == m_pSceneNode)
			{
				m_OgreEngine.m_pCurrentSceneManager->getRootSceneNode()->addChild(m_pCameraFrutsumNode[i]);
			}
			m_pCameraFrutsum[i]->setVisible(false);
			m_pCameraFrutsumNode[i]->setVisible(false);
		}
	}

	processEvents();
	deleteEvents();

	if (m_NetConfig != e_NCNone && m_NetConfig != e_NCServer)
	{
		if (m_SceneName == "Poursuite")
		{
			SetCamera(CNetClient::ms_pSingleton->m_LastPacket.m_Camera.m_Position, 
				CNetClient::ms_pSingleton->m_LastPacket.m_Camera.m_Orientation);
		}
		else
		{
			SetCamera(CNetClient::ms_pSingleton->m_LastPacket.m_Camera.m_Position + (clientPosition - CNetClient::ms_pSingleton->m_LastPacket.m_Camera.m_Position) / 2.0f, 
				Quaternion::Slerp(0.5f, CNetClient::ms_pSingleton->m_LastPacket.m_Camera.m_Orientation, clientOrientation));
			m_OgreEngine.setDebugText("diff: " + StringConverter::toString(clientPosition - CNetClient::ms_pSingleton->m_LastPacket.m_Camera.m_Position));
		}
	}

	{
		if (m_pCameraFrameListener->mInputDevice->isKeyDown(KC_O) && m_pCameraFrameListener->mTimeUntilNextToggle <= 0)
		{
			m_pCurrentCamera->rotate(m_pCurrentCamera->getUp(), Degree(-m_resetParams.m_camSideAngle));
			m_pCameraFrameListener->mTimeUntilNextToggle = 0.3f;
		} else
		if (m_pCameraFrameListener->mInputDevice->isKeyDown(KC_I) && m_pCameraFrameListener->mTimeUntilNextToggle <= 0)
		{
			m_pCurrentCamera->rotate(m_pCurrentCamera->getUp(), Degree(m_resetParams.m_camSideAngle));
			m_pCameraFrameListener->mTimeUntilNextToggle = 0.3f;
		}	
		if (m_pCameraFrameListener->mInputDevice->isKeyDown(KC_NUMPAD8) && m_pCameraFrameListener->mTimeUntilNextToggle <= 0)
		{		
			m_OgreEngine.m_pCurrentSceneManager->setShadowFarDistance(m_OgreEngine.m_pCurrentSceneManager->getShadowFarDistance() + 1);
		} 
		if (m_pCameraFrameListener->mInputDevice->isKeyDown(KC_NUMPAD2) && m_pCameraFrameListener->mTimeUntilNextToggle <= 0)
		{
			m_OgreEngine.m_pCurrentSceneManager->setShadowFarDistance(m_OgreEngine.m_pCurrentSceneManager->getShadowFarDistance() - 1);
		} 
		if (m_pCameraFrameListener->mInputDevice->isKeyDown(KC_NUMPAD7) && m_pCameraFrameListener->mTimeUntilNextToggle <= 0)
		{
			if (m_pCameraFrameListener->mInputDevice->isKeyDown(KC_LSHIFT))
			{
				m_resetParams.m_camSideAngle += Degree(1);
			} else
			if (m_pCameraFrameListener->mInputDevice->isKeyDown(KC_RSHIFT))
			{
				m_resetParams.m_camSideAngle += Degree(0.01);
			}
			else
			{
				m_resetParams.m_camSideAngle += Degree(0.0001);
			}
		} 
		if (m_pCameraFrameListener->mInputDevice->isKeyDown(KC_NUMPAD1) && m_pCameraFrameListener->mTimeUntilNextToggle <= 0)
		{
			if (m_pCameraFrameListener->mInputDevice->isKeyDown(KC_LSHIFT))
			{
				m_resetParams.m_camSideAngle -= Degree(1);
			}
			else
			{
				m_resetParams.m_camSideAngle -= Degree(0.0001);
			}
		} 
		if (m_pCameraFrameListener->mInputDevice->isKeyDown(KC_HOME))
		{
			m_pCurrentCamera->setFocalLength(m_pCurrentCamera->getFocalLength() - 0.01f);
		}	
		if (m_pCameraFrameListener->mInputDevice->isKeyDown(KC_END))
		{
			m_pCurrentCamera->setFocalLength(m_pCurrentCamera->getFocalLength() + 0.01f);
		}	
		if (m_pCameraFrameListener->mInputDevice->isKeyDown(KC_SPACE))
		{
			fakeAddEvent(SOpenMoveDisplayPacket::e_GE_Reset, 0.0f);
		}	
		if (m_pCameraFrameListener->mInputDevice->isKeyDown(KC_BACK))
		{
			fakeAddEvent(SOpenMoveDisplayPacket::e_GE_SetTime, 0.0f);
		}	

        if (m_pCameraFrameListener->mInputDevice->isKeyDown(KC_P) && m_pCameraFrameListener->mTimeUntilNextToggle <= 0)
        {
            displayCameraDetails = !displayCameraDetails;
            m_pCameraFrameListener->mTimeUntilNextToggle = 0.5;
        }
        if (m_pCameraFrameListener->mInputDevice->isKeyDown(KC_LCONTROL) || m_pCameraFrameListener->mInputDevice->isKeyDown(KC_RCONTROL))
		{
			if (m_pCameraFrameListener->mInputDevice->isKeyDown(KC_RIGHT))
			{
				m_Timer.m_ManualSpeed += 0.1;
			}
			if (m_pCameraFrameListener->mInputDevice->isKeyDown(KC_LEFT))
			{
				m_Timer.m_ManualSpeed -= 0.1;
			}
			if (m_pCameraFrameListener->mInputDevice->isKeyDown(KC_UP) && m_pCameraFrameListener->mTimeUntilNextToggle <= 0)
			{
				m_Timer.m_UseManualTime = !m_Timer.m_UseManualTime;
				m_pCameraFrameListener->mTimeUntilNextToggle = 0.5;
				if (m_Timer.m_UseManualTime)
				{
					m_Timer.m_ManualTime = m_Timer.getMilliseconds();
				}
				else
				{
					m_Timer.setTime(m_Timer.m_ManualTime);
				}
			}
		}
        if (m_pCameraFrameListener->mInputDevice->isKeyDown(KC_F) && m_pCameraFrameListener->mTimeUntilNextToggle <= 0)
        {
			fakeAddEvent(SOpenMoveDisplayPacket::e_GE_ShowStats, -1.0f);
        }
		if (displayCameraDetails)
        {
            // Print camera details
			m_OgreEngine.setDebugText("P: " + StringConverter::toString(m_pCurrentCamera->getDerivedPosition()));
			m_OgreEngine.setDebugText("O: " + StringConverter::toString(m_pCurrentCamera->getDerivedOrientation()));
			m_OgreEngine.setDebugText("f:" + StringConverter::toString(Root::getSingleton().getCurrentFrameNumber()));
			m_OgreEngine.setDebugText("shadowFarDistance: " + StringConverter::toString(m_OgreEngine.m_pCurrentSceneManager->getShadowFarDistance()));
			m_OgreEngine.setDebugText("m_SideCamAngle: " + StringConverter::toString(m_resetParams.m_camSideAngle));
			m_OgreEngine.setDebugText("FOVy: " + StringConverter::toString(m_pCurrentCamera->getFOVy()));
			m_OgreEngine.setDebugText("FocalLength: " + StringConverter::toString(m_pCurrentCamera->getFocalLength()));
			m_OgreEngine.setDebugText("AspectRatio: " + StringConverter::toString(m_pCurrentCamera->getAspectRatio()));
        }
		m_OgreEngine.setDebugText("time: " + StringConverter::toString(m_Timer.getSeconds()));
		m_OgreEngine.setDebugText("duration: " + StringConverter::toString(m_resetParams.m_duration));
	}

	if (m_ShowEntitiesBBox)
	{
		for (TSceneLights::const_iterator It = m_SceneLights.begin(); It != m_SceneLights.end(); ++It)
		{
			if (It->m_Name == "Ambient")
			{
				continue;
			}
			else
			{
				Light *light = findLight(String(It->m_Name));
				SceneNode *node = static_cast<SceneNode *>(m_pSceneNode->getChild(It->m_Name));
				if (NULL != light && NULL != node)
				{
					node->setPosition(light->getPosition());
					node->setDirection(light->getDirection(), Node::TS_WORLD);
				}
			}
		}
	}

	if (NULL != m_GuiSheet)
	{
		m_GuiSheet->setVisible(m_pCameraFrameListener->mStatsOn);
		updateGUI();
	}

	m_Timer.m_ManualTime += m_Timer.m_ManualSpeed;

#if SELF_TEST_MODE
	if (m_Timer.getSeconds() > m_resetParams.m_duration && (m_NetConfig == e_NCServer || m_NetConfig == e_NCNone) && m_canSetScene)
	{
		LogManager::getSingleton().logMessage("cmd_setscene " + StringConverter::toString(m_Timer.getSeconds()));
		SShared Command(-1);
		Command.m_Command = CMD_SETSCENE;
		COgreEngine::TScenes::iterator it = find(m_OgreEngine.m_Scenes.begin(), m_OgreEngine.m_Scenes.end(), m_OgreEngine.m_pCurrentScene);
		++it;
		if (it == m_OgreEngine.m_Scenes.end())
		{
			it = m_OgreEngine.m_Scenes.begin();
		}
		Command.m_OSCPacket.sequence_id = (*it)->m_ScenePos;
		CNetServer::ms_pSingleton->addCommand(Command);
		m_canSetScene = false;
	}
#endif

	if (m_Timer.getSeconds() > (m_resetParams.m_duration - m_transitionOut.m_duration))
	{
		CompositorManager::getSingleton().setCompositorEnabled(m_OgreEngine.m_pViewPort, "TransitionOut", true);
		m_transitionIn.m_isActive = false;
		m_transitionOut.m_isActive = true;

		m_OgreEngine.setDebugText("transition out");
		Ogre::LogManager::getSingleton().logMessage("out");
	}
	else
	if (m_Timer.getSeconds() < (m_transitionIn.m_duration))
	{
		CompositorManager::getSingleton().setCompositorEnabled(m_OgreEngine.m_pViewPort, "TransitionIn", true);
		m_transitionIn.m_isActive = true;
		m_transitionOut.m_isActive = false;

		m_OgreEngine.setDebugText("transition in");
		Ogre::LogManager::getSingleton().logMessage("in");
	}
	else
	{
		CompositorManager::getSingleton().setCompositorEnabled(m_OgreEngine.m_pViewPort, "TransitionIn", false);
		CompositorManager::getSingleton().setCompositorEnabled(m_OgreEngine.m_pViewPort, "TransitionOut", false);
		m_transitionIn.m_isActive = false;
		m_transitionOut.m_isActive = false;

		m_OgreEngine.setDebugText("transition off");
		Ogre::LogManager::getSingleton().logMessage("off: " + StringConverter::toString(m_Timer.getSeconds()));
	}

	if (!m_isSceneReady && (m_NetConfig == e_NCNone || m_NetConfig == e_NCServer))
	{
		m_Timer.reset();
	}

	++nbFrameElapsed;

	m_isSceneReady = nbFrameElapsed > NB_FRAME_BEFORE_READY;

	return (true);
}

void CSceneBase :: deleteEvents(void)
{
	size_t const Size = m_Events.size();
	for (TEvents::iterator It = m_Events.begin(); It != m_Events.end();)
	{
		if (It->isOver())
		{
			It = m_Events.erase(It);
		}
		else
		{
			++It;
		}
	}
}

void CSceneBase :: processEvents(void)
{
	m_OgreEngine.setDebugText("Events:\n");

	{
		size_t const listSize = m_EventsList.size();
		size_t current = 0;
		for (size_t i = 0; i < listSize; ++i)
		{
			SEvent &It = m_EventsList.at(current);
			//if (m_Timer.getMilliseconds() >= It.m_StartTime)
			{
				m_Events.push_back(It);
				m_EventsList.erase(m_EventsList.begin() + current);
			}
			/*
			else
			{
				++current;
			}
			*/
		}
	}

	for (TEvents::iterator It = m_Events.begin(); It != m_Events.end(); ++It)
	{
		if (It->m_IsFirstTime)
		{
			It->m_IsFirstTime = false;
		}
		else
		if (It->m_HasStarted)
		{
			It->m_IsFirstTime = true;
			It->m_HasStarted = false;
		}

		if (It->m_Packet.eventid == SOpenMoveDisplayPacket::e_GE_SetTime && m_ScenePos == It->m_Packet.sequence_id)
		{
			Real curTime = m_Timer.getSeconds();
			Real diffTime = It->m_Packet.time - curTime;
			m_interactionTime = (diffTime / (m_resetParams.m_duration - curTime));
			timeFromPacket = It->m_Packet.time;
		}
		else
		if (It->m_Packet.eventid == SOpenMoveDisplayPacket::e_GE_Reset)
		{
			Reset();
		}
		else
		if (It->m_Packet.eventid == SOpenMoveDisplayPacket::e_GE_ShowStats)
		{
            m_pCameraFrameListener->mStatsOn = !m_pCameraFrameListener->mStatsOn;
            m_pCameraFrameListener->showDebugOverlay(m_pCameraFrameListener->mStatsOn);
			m_OgreEngine.m_statsOn = m_pCameraFrameListener->mStatsOn;

            m_pCameraFrameListener->mTimeUntilNextToggle = 1;
		}

		m_OgreEngine.setDebugText(
			"- " + getEventName(It->m_Packet.eventid) + ":" +
			StringConverter::toString(It->m_pTimer->getMilliseconds() / 1000.0f) + "/" + 
			StringConverter::toString(It->m_Packet.duree));
	}
}

void CSceneBase :: updateAnim(const FrameEvent &evt)
{
	unsigned int current = 0;
	for (TEntities::iterator ItEntity = m_Entities.begin(); ItEntity != m_Entities.end(); ++ItEntity)
	{
		AnimationStateSet *pStateSet = (*ItEntity)->getAllAnimationStates();
		if (NULL != pStateSet)
		{
			AnimationStateIterator It = pStateSet->getAnimationStateIterator();
			while(It.hasMoreElements())
			{
				AnimationState * pState = It.getNext();
				if (m_NetConfig == e_NCNone || m_NetConfig == e_NCServer)
				{
					pState->setTimePosition(GetAnimationsFrame() / 1000.0f);
				}
				else
				{				
					htMutexLock(&CSyncManager::getSingleton().m_updateMutex);
					Real frame = m_animPacket[current] +
					(GetAnimationsFrame() + m_OgreEngine.m_pCurrentRenderWindow->getLastFPS() * 3.0f) / 1000.0f;
					pState->setTimePosition(m_animPacket[current]);
					htMutexUnlock(&CSyncManager::getSingleton().m_updateMutex);
				}

				if (0)
				{
				m_OgreEngine.setDebugText("anim " + StringConverter::toString(current) + 
					": " + StringConverter::toString(m_animPacket[current]));
				}

				++current;
			}
		}
	}
}

void CSceneBase :: addEvent(SOpenMoveDisplayPacket const &packet, Real const startTime)
{
	bool found = false;

	for (TEvents::iterator It = m_Events.begin(); It != m_Events.end(); ++It)
	{
		if (packet.eventid == It->m_Packet.eventid)
		{
			found = true;
			break;
		}
	}
	if (!found)
	{
		for (TEvents::iterator It = m_EventsList.begin(); It != m_EventsList.end(); ++It)
		{
			if (packet.eventid == It->m_Packet.eventid)
			{
				found = true;
				break;
			}
		}
	}

	if (!found)
	{
		SEvent event(m_NextEventId, packet, startTime);
		m_EventsList.push_back(event);
		++m_NextEventId;
	}	
}

void CSceneBase :: fakeAddEvent(int Id, Real Duration, String &params, Real const speed, Vector3 const pos, SOpenMoveDisplayPacket::MessageType type)
{
	if (e_NCNone != m_NetConfig && NULL != CNetServer::ms_pSingleton)
	{
		SOpenMoveDisplayPacket Packet;
		Packet.type = type;
		Packet.eventid = (SOpenMoveDisplayPacket::MessageType)Id;
		Packet.duree = Duration;
		Packet.user_position_h = pos.x;
		Packet.user_position_v = pos.z;
		Packet.user_speed = speed;
		//Packet.time = m_Timer.getSeconds() + 5.0f;
		snprintf(Packet.params, sizeof(Packet.params), "%s", params.c_str());
		CNetServer::ms_pSingleton->ProcessPacket(reinterpret_cast<char *>(&Packet), sizeof(Packet), IpEndpointName::ANY_ADDRESS);
	}
	else
	{
		SOpenMoveDisplayPacket Packet;
		Packet.type = type;
		Packet.eventid = (SOpenMoveDisplayPacket::MessageType)Id;
		Packet.duree = Duration;
		Packet.user_position_h = pos.x;
		Packet.user_position_v = pos.z;
		Packet.user_speed = speed;
		//Packet.time = m_Timer.getSeconds() + 5.0f;
		snprintf(Packet.params, sizeof(Packet.params), "%s", params.c_str());
		addEvent(Packet, m_Timer.getMilliseconds() + 48.0f);
	}
}

SEvent :: SEvent(unsigned long eventId, SOpenMoveDisplayPacket const &packet, Real startTime) : m_Packet(packet), m_pTimer(NULL), m_StartTime(startTime), m_EventId(eventId)
{
	m_pTimer = new OMTimer();
	m_pTimer->reset();	

	m_IsFirstTime = false;
	m_HasStarted = true;
}

SEvent :: ~SEvent(void)
{
	delete m_pTimer;
}

bool SEvent :: isOver(void)
{
	return (m_pTimer->getMilliseconds() > m_Packet.duree * 1000.0f);
}

void CSceneBase :: keyReleased(KeyEvent* e)
{
	if (KC_ADD == e->getKey())
	{
		if (m_NetConfig == e_NCNone)
		{
			m_OgreEngine.startNextScene();
		}
		else
		{
			SShared Command(-1);
			Command.m_Command = CMD_SETSCENE;
			COgreEngine::TScenes::iterator it = find(m_OgreEngine.m_Scenes.begin(), m_OgreEngine.m_Scenes.end(), m_OgreEngine.m_pCurrentScene);
			++it;
			if (it == m_OgreEngine.m_Scenes.end())
			{
				it = m_OgreEngine.m_Scenes.begin();
			}
			Command.m_OSCPacket.sequence_id = (*it)->m_ScenePos;
			CNetServer::ms_pSingleton->addCommand(Command);
		}
	}
	if (KC_MINUS == e->getKey())
	{
		if (m_NetConfig == e_NCNone)
		{
			m_OgreEngine.startPreviousScene();
		}
		else
		{
			SShared Command(-1);
			Command.m_Command = CMD_SETSCENE;
			COgreEngine::TScenes::iterator it = find(m_OgreEngine.m_Scenes.begin(), m_OgreEngine.m_Scenes.end(), m_OgreEngine.m_pCurrentScene);
			if (it == m_OgreEngine.m_Scenes.begin())
			{
				Command.m_OSCPacket.sequence_id = m_OgreEngine.m_Scenes.back()->m_ScenePos;
			}
			else
			{
				--it;
				Command.m_OSCPacket.sequence_id = (*it)->m_ScenePos;
			}

			CNetServer::ms_pSingleton->addCommand(Command);
		}
	}

	if (KC_F9 == e->getKey())
	{
		m_pCameraFrameListener->setMoveCamera(!m_pCameraFrameListener->getMoveCamera());
	}

   CEGUI::System::getSingleton().injectKeyUp(e->getKey());
   e->consume();
}

void CSceneBase :: keyPressed(KeyEvent* e)
{
   CEGUI::System::getSingleton().injectKeyDown(e->getKey());
   CEGUI::System::getSingleton().injectChar(e->getKeyChar());
   e->consume();
}

void CSceneBase :: keyClicked(KeyEvent* e)
{
}

bool CSceneBase :: frameEnded(const FrameEvent& evt)
{
	if (!m_transitionIn.m_isActive && !m_transitionOut.m_isActive && (e_NCServer == m_NetConfig || e_NCNone == m_NetConfig))
	{
		Real curTime = m_Timer.getMilliseconds();
		m_Timer.setTime(curTime + (m_OgreEngine.m_pCurrentRenderWindow->getLastFPS()) * m_interactionTime);

		m_OgreEngine.setDebugText("m_duration: " + StringConverter::toString(m_resetParams.m_duration) + 
			" m_interactionTime: " + StringConverter::toString(m_interactionTime) +
			" timeFromPacket: " + StringConverter::toString(timeFromPacket) + 
			" curTime: " + StringConverter::toString(curTime)
			);

	}

	if (m_NetConfig == e_NCNone || m_NetConfig == e_NCServer)
	{
		htMutexLock(&CSyncManager::getSingleton().m_updateMutex);
	unsigned int current = 0;
	for (TEntities::iterator ItEntity = m_Entities.begin(); ItEntity != m_Entities.end(); ++ItEntity)
	{
		AnimationStateSet *pStateSet = (*ItEntity)->getAllAnimationStates();
		if (NULL != pStateSet)
		{
			AnimationStateIterator It = pStateSet->getAnimationStateIterator();
			while(It.hasMoreElements())
			{
				if (current >= MAX_ANIM)
					OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, "too many anims", "CSceneBase :: frameEnded" );


				AnimationState * pState = It.getNext();
				m_animPacket[current] = pState->getTimePosition() + (3.0f / m_OgreEngine.m_pCurrentRenderWindow->getLastFPS());

				++current;
			}
		}
	}
	htMutexUnlock(&CSyncManager::getSingleton().m_updateMutex);
	}

	return (true);
}

void CSceneBase :: SetCamera(Vector3 const &position, Quaternion const &orientation, bool fake)
{
	if (!fake)
	{
		m_pCurrentCamera->setPosition(position);
		m_pCurrentCamera->setOrientation(orientation);
	}

	for (size_t i = 0; i < e_NbCamera; ++i)
	{
		m_pCameraFrutsum[i]->getParentSceneNode()->setPosition(position);
		m_pCameraFrutsum[i]->getParentSceneNode()->setOrientation(orientation);
		m_pCameraFrutsum[i]->setFOVy(m_pCurrentCamera->getFOVy());
		m_pCameraFrutsum[i]->setFocalLength(m_pCurrentCamera->getFocalLength());
		m_pCameraFrutsum[i]->setAspectRatio(m_pCurrentCamera->getAspectRatio());
	}

	m_pCameraFrutsum[1]->getParentSceneNode()->rotate(m_pCameraFrutsum[0]->getUp(), m_resetParams.m_camSideAngle);
	m_pCameraFrutsum[2]->getParentSceneNode()->rotate(m_pCameraFrutsum[0]->getUp(), -m_resetParams.m_camSideAngle);

	switch (m_NetConfig)
	{
		case e_NCClientL:
		{
			m_pCurrentCamera->rotate(m_pCurrentCamera->getUp(), m_resetParams.m_camSideAngle);
			break;
		}
		case e_NCClientR:
		{
			m_pCurrentCamera->rotate(m_pCurrentCamera->getUp(), -m_resetParams.m_camSideAngle);
			break;
		}
		default:
		{			
			break;
		}
	}
}

CompositorInstance * CSceneBase :: findCompositor(String &Name)
{
	return (reinterpret_cast<CompositorInstance *>(CompositorManager::getSingleton().getByName(Name).getPointer()));
}


void CSceneBase :: mouseMoved (MouseEvent *e)
{
   CEGUI::System::getSingleton().injectMouseMove(
		e->getRelX() * m_OgreEngine.m_GUIRenderer->getWidth(), 
		e->getRelY() * m_OgreEngine.m_GUIRenderer->getHeight());
   e->consume();
}

void CSceneBase :: mouseDragged (MouseEvent *e) 
{ 
   mouseMoved(e);
}

void CSceneBase :: mousePressed (MouseEvent *e)
{
   CEGUI::System::getSingleton().injectMouseButtonDown(
     m_OgreEngine.convertOgreButtonToCegui(e->getButtonID()));
   e->consume();
}

void CSceneBase :: mouseReleased (MouseEvent *e)
{
	CEGUI::System::getSingleton().injectMouseButtonUp(m_OgreEngine.convertOgreButtonToCegui(e->getButtonID()));

	CEGUI::StaticText *selectionText = (CEGUI::StaticText *)m_GuiSheet->getChild(String(m_SceneName + "CurrentSelection").c_str());

	if ( selectionText != NULL && !m_LightEditorSheet->isActive()) 
	{
		// Start a new ray query
		Ogre::Ray cameraRay = m_pCurrentCamera->getCameraToViewportRay(e->getX(), e->getY());
		Ogre::RaySceneQuery *raySceneQuery = m_OgreEngine.m_pCurrentSceneManager->createRayQuery( cameraRay );
		raySceneQuery->execute();

		Ogre::RaySceneQueryResult result = raySceneQuery->getLastResults();
		Ogre::MovableObject *closestObject = NULL;
		Real closestDistance = LONG_MAX;
		Ogre::RaySceneQueryResult::iterator rayIterator;

		size_t currentSel = 0;
		size_t selIndex = -1;
		Real currentTime = m_Timer.getSeconds();

		rayIterator = result.begin();
		for (Ogre::RaySceneQueryResult::iterator rayIterator2 = result.begin();	rayIterator2 != result.end(); rayIterator2++) 
		{
			int r = (int)(*rayIterator2).movable->getName().find("Camera");
			if (selectionText->getText() == (*rayIterator2).movable->getName() && r < 0)
			{
				if (++rayIterator2 != result.end())
				{
					rayIterator = rayIterator2;
					break;
				}
				else
				{
					rayIterator = result.begin();
					break;
				}
			}
		}

		for (;	rayIterator != result.end(); rayIterator++) 
		{
			int r = (int)(*rayIterator).movable->getName().find("Camera");
			if (( *rayIterator ).distance < closestDistance && r < 0)
			{
				closestObject = ( *rayIterator ).movable;
				closestDistance = ( *rayIterator ).distance;
				selIndex = currentSel;
			}

			++currentSel;
		}
		if (NULL != closestObject)
		{
			if (closestObject->getName() == selectionText->getText() && result.size() > 1)
			{
				if (selIndex < result.size() - 1)
				{
					closestObject = result[selIndex + 1].movable;
					closestDistance = result[selIndex + 1].distance;
				}
				else
				{
					closestObject = result[0].movable;
					closestDistance = result[0].distance;
				}
			}


			setGUI(closestObject);
		}

		raySceneQuery->clearResults();
		m_OgreEngine.m_pCurrentSceneManager->destroyQuery( raySceneQuery );
	}

	e->consume();
}

void CSceneBase :: setupEventHandlers(void)
{
   CEGUI::WindowManager& wmgr = CEGUI::WindowManager::getSingleton();

   m_GuiSheet->getChild((CEGUI::utf8*)String(m_SceneName + "Quit").c_str())->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&CSceneBase::handleQuitEvent, this));
   m_TimeSlider->subscribeEvent(CEGUI::Scrollbar::EventThumbTrackStarted, CEGUI::Event::Subscriber(&CSceneBase::handleThumbTrackStarted, this));
   m_TimeSlider->subscribeEvent(CEGUI::Scrollbar::EventThumbTrackEnded, CEGUI::Event::Subscriber(&CSceneBase::handleThumbTrackEnded, this));
   m_TimeSlider->subscribeEvent(CEGUI::Scrollbar::EventScrollPositionChanged, CEGUI::Event::Subscriber(&CSceneBase::handleScrollPositionChanged, this));
}

bool CSceneBase :: handleQuitEvent(const CEGUI::EventArgs& e)
{
	m_pCameraFrameListener->mRequestShutdown = true;

	return true;
}

void CSceneBase :: setupSheet(void)
{
	CEGUI::WindowManager &wmgr = CEGUI::WindowManager::getSingleton();

	CEGUI::Logger::getSingleton().setLoggingLevel(CEGUI::Informative);
	{
		m_GuiSheet = CEGUI::WindowManager::getSingleton().createWindow((CEGUI::utf8*)"DefaultWindow", (CEGUI::utf8*)m_SceneName.c_str());

		CEGUI::PushButton* quitButton = (CEGUI::PushButton*)wmgr.createWindow("TaharezLook/Button", (CEGUI::utf8*)String(m_SceneName + "Quit").c_str());
		m_GuiSheet->addChildWindow(quitButton);
		quitButton->setPosition(CEGUI::Point(0.f, 0.f));
		quitButton->setSize(CEGUI::Size(0.1f, 0.05f));
		quitButton->setText("Quit");

		CEGUI::StaticText *selectionText = (CEGUI::StaticText*)wmgr.createWindow("TaharezLook/StaticText", (CEGUI::utf8*)String(m_SceneName + "CurrentSelection").c_str());
		m_GuiSheet->addChildWindow(selectionText);
		selectionText->setPosition(CEGUI::Point(0.1f, 0.f));
		selectionText->setSize(CEGUI::Size(0.3f, 0.05f));
		selectionText->setText("None");

		m_TimeSlider = (CEGUI::Scrollbar*)wmgr.createWindow("TaharezLook/HorizontalScrollbar", (CEGUI::utf8*)String(m_SceneName + "TimeSlider").c_str());
		m_GuiSheet->addChildWindow(m_TimeSlider);
		m_TimeSlider->setPosition(CEGUI::Point(0.4f, 0));
		m_TimeSlider->setSize(CEGUI::Size(0.6f, 0.05f));
		m_TimeSlider->setDocumentSize(m_resetParams.m_duration * 1000.0f);
		m_TimeSlider->setStepSize(33.33f);
		m_TimeSlider->setScrollPosition(m_Timer.getMilliseconds());

		/*
		CEGUI::Combobox *comboBox = (CEGUI::Combobox*)wmgr.createWindow("TaharezLook/ComboBox", (CEGUI::utf8*)String(m_SceneName + "Lights").c_str());
		m_GuiSheet->addChildWindow(comboBox);
		comboBox->setPosition(CEGUI::Point(0.1f, 0.05f));
		comboBox->setSize(CEGUI::Size(0.3f, 0.05f));
		for (TSceneLights::iterator it = m_SceneLights.begin(); it != m_SceneLights.end(); ++it)
		{
			String name = (*it).getName();
			//CEGUI::ListboxItem *item = new CEGUI::ListboxItem();
			//comboBox->addItem(item);
		}
		*/
	}

	if (NULL == m_LightEditorSheet)
	{
		m_LightEditorSheet = new LightEditor(m_GuiSheet, m_OgreEngine.m_pCurrentSceneManager);
	}
}

void CSceneBase :: setGUI(MovableObject *currentObject)
{
	m_CurrentObject = currentObject;

	m_LightEditorSheet->setVisible(false);

	if (currentObject)
	{
		CEGUI::StaticText *selectionText = (CEGUI::StaticText *)m_GuiSheet->getChild(String(m_SceneName + "CurrentSelection").c_str());
		if ( selectionText != NULL ) 
		{
			selectionText->setText(currentObject->getName());
		}

		if (SceneManager::ENTITY_TYPE_MASK == currentObject->getTypeFlags())
		{
			Light *light = findLight(String(currentObject->getName()));
			if (NULL != light)
			{
				m_LightEditorSheet->setVisible(true);
				m_LightEditorSheet->updateSliders(light);
			}
		}
	}
}

void CSceneBase :: updateGUI(void)
{
	if (!m_sliding)
	{
		m_TimeSlider->setScrollPosition(m_Timer.getMilliseconds());
	}
	else
	{
		//m_Timer.m_ManualTime = m_TimeSlider->getScrollPosition();
		m_Timer.setTime(m_TimeSlider->getScrollPosition());
	}

	if (!m_Timer.m_UseManualTime)
	{
		m_TimeSlider->setScrollPosition(m_Timer.getMilliseconds());
	}
	else
	{
		CSyncManager::getSingleton().m_Timer.setTime(m_Timer.getMilliseconds());
	}

	if (m_CurrentObject)
	{
		if (SceneManager::ENTITY_TYPE_MASK == m_CurrentObject->getTypeFlags())
		{
			Light *light = findLight(String(m_CurrentObject->getName()));
			if (NULL != light)
			{
				m_LightEditorSheet->updateLight(light);
			}
		}
	}
}

bool CSceneBase :: handleThumbTrackStarted(const CEGUI::EventArgs& e)
{
	m_sliding = true;
	return (true);
}

bool CSceneBase :: handleThumbTrackEnded(const CEGUI::EventArgs& e)
{
	m_sliding = false;
	//m_Timer.m_ManualTime = m_TimeSlider->getScrollPosition();
	m_Timer.setTime(m_TimeSlider->getScrollPosition());
	return (true);
}

bool CSceneBase :: handleScrollPositionChanged(const CEGUI::EventArgs& e)
{
	//m_Timer.m_ManualTime = m_TimeSlider->getScrollPosition();
	m_Timer.setTime(m_TimeSlider->getScrollPosition());
	return (true);
}


void CSceneBase :: notifyMaterialSetup(uint32 pass_id, MaterialPtr &mat)
{
	if (mat->getNumTechniques() > 0 && mat->getTechnique(0)->getNumPasses() > 0)
	{
		if (pass_id == 0 && mat->getTechnique(0)->getPass(0)->getName() == "TransitionOut")
		{
			Pass *pass = mat->getTechnique(0)->getPass(0);
			if (NULL != pass)
			{
				m_transitionOut.m_fpParams = pass->getFragmentProgramParameters();
			}
		}
		if (pass_id == 0 && mat->getTechnique(0)->getPass(0)->getName() == "TransitionIn")
		{
			Pass *pass = mat->getTechnique(0)->getPass(0);
			if (NULL != pass)
			{
				m_transitionIn.m_fpParams = pass->getFragmentProgramParameters();
			}
		}
	}
}

void CSceneBase :: notifyMaterialRender(uint32 pass_id, MaterialPtr &material)
{
	Real curTime = m_Timer.getSeconds();

	if (curTime > (m_resetParams.m_duration - m_transitionOut.m_duration))
	{
	if(m_transitionInIsPassed && m_transitionOut.m_isActive && !m_transitionOut.m_fpParams.isNull() && m_transitionOut.m_fpParams->hasRealConstantParams())
    {

		// fade to black
		Real black = 1.0f;

		if (-1.0f == m_transitionOut.m_black)
		{
			Real val = true == m_transitionOut.m_isBW ? m_transitionOut.m_duration / 4.0f : m_transitionOut.m_duration;
			black = 1.0f - (curTime - ((m_resetParams.m_duration) - val)) / val;
			black = std::max(black, 0.0f);
			black = std::min(black, 1.0f);
		}

		Real deform = 0.0f;
		if (-1.0f == m_transitionOut.m_deform)
		{
			deform = (curTime - ((m_resetParams.m_duration) - m_transitionOut.m_duration));
		}

		Real add = 0.0f;
		if (-1.0f == m_transitionOut.m_add)
		{
			add = ((curTime - ((m_resetParams.m_duration) - m_transitionOut.m_duration)) /m_transitionOut.m_duration) * 1.0f;
			add = std::max(add, 0.01f);
			add = std::min(add, 0.99f);
		}
		
		Real deformation = 1.0f;
		if (true == m_transitionOut.m_deformAnim)
		{
			deformation = fmod(curTime, 1);
		}
		
		Real bwColor = 1.0f;
		if (true == m_transitionOut.m_isBW)
		{
			bwColor = 1.0f - ((curTime - ((m_resetParams.m_duration) - m_transitionOut.m_duration)) / m_transitionOut.m_duration);
		}

		Vector4 value(deform, black, add, 0);
		m_transitionOut.m_fpParams->setNamedConstant("value", value);
		m_transitionOut.m_fpParams->setNamedConstant("time", deformation);
		m_transitionOut.m_fpParams->setNamedConstant("bwColor", Vector3(bwColor, bwColor, bwColor));
	}
	}


	if (curTime < (m_transitionIn.m_duration))
	{
	if (m_transitionIn.m_isActive && !m_transitionIn.m_fpParams.isNull() && m_transitionIn.m_fpParams->hasRealConstantParams())
    {
		m_transitionInIsPassed = true;

		// fade to black
		Real black = 1.0f;
		if (-1.0f == m_transitionIn.m_black)
		{
			black = curTime / (true == m_transitionIn.m_isBW ? m_transitionIn.m_duration / 4.0f : m_transitionIn.m_duration);
			black = std::max(black, 0.0f);
			black = std::min(black, 1.0f);
		}

		Real deform = 0.0f;
		if (-1.0f == m_transitionIn.m_deform)
		{
			deform = m_transitionIn.m_duration - (curTime - (m_resetParams.m_duration - m_transitionIn.m_duration));
		}

		Real add = 0.0f;
		if (-1.0f == m_transitionIn.m_add)
		{
			add = 1.0f - (curTime / m_transitionIn.m_duration);
			add = std::max(add, 0.01f);
			add = std::min(add, 0.99f);
		}
		
		Real deformation = 1.0f;
		if (true == m_transitionIn.m_deformAnim)
		{
			deformation = fmod(curTime, 1);
		}

		Real bwColor = 1.0f;
		if (true == m_transitionIn.m_isBW)
		{
			bwColor = (curTime / m_transitionIn.m_duration);
		}
		
		Vector4 value(deform, black, add, 0);
		m_transitionIn.m_fpParams->setNamedConstant("value", value);
		m_transitionIn.m_fpParams->setNamedConstant("time", deformation);
		m_transitionIn.m_fpParams->setNamedConstant("bwColor", Vector3(bwColor, bwColor, bwColor));

		Ogre::LogManager::getSingleton().logMessage("in: " + StringConverter::toString(curTime));
	}
	}
}

CSceneTimer :: CSceneTimer(ENetConfig netConfig) : m_UseManualTime(false),
m_ManualTime(0),
m_ManualSpeed(0),
m_netConfig(netConfig)
{
}

Real CSceneTimer :: getMilliseconds(void)
{
	if (m_UseManualTime)
	{
		return m_ManualTime;
	}

	if (m_netConfig == e_NCClientL || m_netConfig == e_NCClientR)
	{
		//return m_ManualTime;
	}

	return m_timer.getMilliseconds();
}

Real CSceneTimer :: getSeconds(void)
{
	if (m_UseManualTime)
	{
		return m_ManualTime / 1000.0f;
	}

	if (m_netConfig == e_NCClientL || m_netConfig == e_NCClientR)
	{
		//return m_ManualTime / 1000.0f;
	}

	return m_timer.getSeconds();
}

void CSceneTimer :: reset(void)
{
	if (m_netConfig == e_NCClientL || m_netConfig == e_NCClientR)
	{
		//m_ManualTime = 0.0f;
	}

	m_timer.reset();

	LogManager::getSingleton().logMessage("Reset");
}

void CSceneTimer :: setTime(Real const val)
{
	m_ManualTime = val;
	m_timer.setTime(val);
}
